package com.wfh.mianshiji.ai.chatmemory;

import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wfh.mianshiji.constant.RedisPrefixConstant;
import com.wfh.mianshiji.model.dto.ChatMessageDto;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author fenghuanwang
 */
@Component
@Slf4j
public class InterviewRedisChatMemory implements ChatMemory {



    @Resource(name = "chatRedisTemplate")
    private RedisTemplate<String, String> redisTemplate;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private String buildKey(String conversationId) {
        return RedisPrefixConstant.CHAT_HISTORY_PREFIX + conversationId;
    }

    @Override
    public void add(String conversationId, List<Message> messages) {
        if (messages == null || messages.isEmpty()){
            return;
        }

        String key = buildKey(conversationId);
        List<String> jsonMessages = new ArrayList<>();

        for (Message message : messages) {
            String role = switch (message.getMessageType()) {
                case USER -> "user";
                case ASSISTANT -> "ai";
                default -> null;
            };
            if (role == null) {
                log.warn("跳过未知消息类型: {}", message.getMessageType());
                continue;
            }

            ChatMessageDto dto = new ChatMessageDto(role, message.getText());
            try {
                String json = objectMapper.writeValueAsString(dto);
                jsonMessages.add(json);
            } catch (JsonProcessingException e) {
                log.error("序列化消息失败", e);
            }
        }

        if (!jsonMessages.isEmpty()) {
            // 从左侧还是右侧 push？Spring AI 通常按时间顺序追加 → 用 right push (RPUSH)
            redisTemplate.opsForList().rightPushAll(key, jsonMessages);
        }
    }

    @Override
    public List<Message> get(String conversationId, int lastN) {
        String key = buildKey(conversationId);
        try {
            // Redis List: 最旧在左，最新在右
            // 获取最后 lastN 条：从 -lastN 到 -1
            long size = redisTemplate.opsForList().size(key);
            if (ObjectUtil.isEmpty(size) || size == 0) {
                return Collections.emptyList();
            }

            long start = Math.max(0, size - lastN);
            List<String> jsonList = redisTemplate.opsForList().range(key, start, -1);
            if (jsonList == null || jsonList.isEmpty()) {
                return Collections.emptyList();
            }

            return jsonList.stream()
                    .map(this::jsonToMessage)
                    .filter(java.util.Objects::nonNull)
                    .collect(Collectors.toList());

        } catch (Exception e) {
            log.error("从 Redis 获取对话失败, conversationId: {}", conversationId, e);
            return Collections.emptyList();
        }
    }

    private Message jsonToMessage(String json) {
        try {
            ChatMessageDto dto = objectMapper.readValue(json, ChatMessageDto.class);
            return switch (dto.getRole()) {
                case "user" -> new UserMessage(dto.getContent());
                case "ai" -> new AssistantMessage(dto.getContent());
                default -> null;
            };
        } catch (Exception e) {
            log.warn("反序列化消息失败: {}", json, e);
            return null;
        }
    }

    @Override
    public void clear(String conversationId) {
        String key = buildKey(conversationId);
        redisTemplate.delete(key);
    }
}